use std::net::{TcpStream, UdpSocket};
use std::io::{self, Write, Read};
// use std::thread;
use std::sync::{Arc, Mutex};
// use std::time::Duration;
use crate::common::event::AppEvent;

#[derive(Debug)]
pub enum Protocol {
    Tcp,
    Udp,
    Butt,
}

#[derive(Debug)]
pub struct SocketConnection {
    protocol: Protocol,
    address: String,
    port: u16,
    stream: Option<Arc<Mutex<TcpStream>>>,
    udp_socket: Option<Arc<Mutex<UdpSocket>>>,
}

impl SocketConnection {
    pub fn new() -> Self {
        Self {
            protocol: Protocol::Butt,
            address: String::new(),
            port: 0,
            stream: None,
            udp_socket: None,
        }
    }

    pub fn connect(&mut self, protocol: Protocol, address: String, port: u16) -> io::Result<()> {
        match self.protocol {
            Protocol::Tcp => {
                let stream = TcpStream::connect((self.address.as_str(), self.port))?;
                self.stream = Some(Arc::new(Mutex::new(stream)));
            }
            Protocol::Udp => {
                let socket = UdpSocket::bind("0.0.0.0:0")?;
                socket.connect((self.address.as_str(), self.port))?;
                self.udp_socket = Some(Arc::new(Mutex::new(socket)));
            }
            Protocol::Butt => {
                println!("Protocol not supported");
            }
        }
        Ok(())
    }

    pub fn disconnect(&mut self) {
        self.stream = None;
        self.udp_socket = None;
    }

    pub fn send(&self, data: &[u8]) -> io::Result<()> {
        match &self.protocol {
            Protocol::Tcp => {
                if let Some(stream) = &self.stream {
                    let mut stream = stream.lock().unwrap();
                    stream.write_all(data)?;
                }
            }
            Protocol::Udp => {
                if let Some(socket) = &self.udp_socket {
                    let socket = socket.lock().unwrap();
                    socket.send(data)?;
                }
            }
            Protocol::Butt => {
                println!("Protocol not supported");
            }
        }
        Ok(())
    }

    pub fn receive(&self, buffer: &mut [u8]) -> io::Result<usize> {
        match &self.protocol {
            Protocol::Tcp => {
                if let Some(stream) = &self.stream {
                    let mut stream = stream.lock().unwrap();
                    stream.read(buffer)
                } else {
                    Err(io::Error::new(io::ErrorKind::NotConnected, "Not connected"))
                }
            }
            Protocol::Udp => {
                if let Some(socket) = &self.udp_socket {
                    let socket = socket.lock().unwrap();
                    socket.recv(buffer)
                } else {
                    Err(io::Error::new(io::ErrorKind::NotConnected, "Not connected"))
                }
            }
            Protocol::Butt => {
                Err(io::Error::new(io::ErrorKind::Other, "Protocol not supported"))
            }
        }
    }

    pub fn handle_event(&self, event : &AppEvent) {
        println!("RightPanel handleEvent {:?}", event);
    }
}